
/**
 *Clase que representa a una cola utilizando a una lista circularmente encadenada. Por utilizar una lista ciruclar como base, se definio que el inicio de la cola seria el final de la lista circular y que el final de cola seria el inicio de la lista circular.
 * @param <E> permite que la cola sea generica.
 * @author Alejo
 */
public class ImpleCircular<E> extends QueueAbstract<E> {
    
    private Nodo<E> tail;
    /**
     * Constructor de una cola vacia.
     */
    public ImpleCircular(){
        tail = null;
        cp = 0;
   
    }
    
    /**
     * Procedimiento que permite agregar al inicio de una list circular
     * @param value Se envia como paramentro el elemento que se desea agregar.
     */
    public void addFirst(E value){
        Nodo<E> temp = new Nodo<E>(value);
        if (tail == null) { // first value added
            tail = temp;
            tail.setNext(tail);
        } 
        else { // element exists in list
            temp.setNext(tail.next());
            tail.setNext(temp);
            }
        cp++;
    }
    /**
     * Si la cola no esta vacia permite obtener y luego remover al elemento que se encuentra al final de lista circular
     * @return Devuelve al elemento que se encuentra al final de la lista circular.
     */
    public E removeLast()
        // pre: !isEmpty()
        // post: returns and removes value from tail of list
            {
            Nodo<E> finger = tail;
            while (finger.next() != tail) {
            finger = finger.next();
            }
            // finger now points to second-to-last value
            Nodo<E> temp = tail;
            if (finger == tail)
            {
            tail = null;
            } else {
            finger.setNext(tail.next());
            tail = finger;
            }
            cp--;
            return temp.value();
            }
    /**
     * Procedimiento que permite agregar un elemento al final de cola,     
     * @param value Recibe como parametro el elemento que se desea agregar.
     */
    @Override
    public void offer(E value) {
        addFirst(value);
    }

    /**
     * Procedimiento que permite obtener y luego retirar de una cola al elemento que se encuentra al incio de la cola.
     * @return Devuelve al elemento que se encuentre al inicio de la cola.
     */
    @Override
    public E poll() {
        E data;
        data = removeLast();
        return data;
    }

    /**
     * Procedimiento que permite obtener al elemento que se encuentra al inicio de la cola sin removerlo de la misma.
     * @return Devuelve al elemento que se encuentra al inicio de la cola.
     */
    @Override
    public E peek() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
}
